package com.platform.common.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.platform.common.result.ApiException;
import com.platform.common.result.ApiExceptionEnum;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description DTO-DO 特殊转换方法的统一收口处
 * @author GH
 **/
public class BaseConvertUtils {

    /**
     * 常用 DO、DTO 转换方法
     **/

    public static List<String> stringToList(String str) {
        return StringUtils.isBlank(str) ? new ArrayList<>() : Arrays.stream(str.split(",")).collect(Collectors.toList());
    }

    public static Set<String> stringToSet(String str) {
        return StringUtils.isBlank(str) ? null : Arrays.stream(str.split(",")).collect(Collectors.toSet());
    }

    public static String listToString(List<String> list) {
        return collectionToString(list);
    }

    public static String setToString(Set<String> list) {
        return collectionToString(list) == null ? "" : collectionToString(list);
    }

    private static String collectionToString(Collection<String> collection) {
        if (CollectionUtils.isEmpty(collection)) {
            return null;
        }

        AssertUtils.isTrue(collection.stream().allMatch(o -> StringUtils.containsNone(o, ',')), ApiExceptionEnum.PARAM_NOT_VALID,
                "字段中不能包含 , ");
        return StringUtils.join(collection, ',');
    }

    public static Map<String, String> stringToMap(String str) {
        return StringUtils.isBlank(str) ? null : Arrays.stream(str.split(";")).collect(Collectors.toMap(s -> s.substring(0, s.indexOf(":")), s -> s.substring(s.indexOf(":") + 1), (k1, k2) -> k1));
    }

    public static String mapToString(Map<String, String> map) {
        if (CollectionUtils.isEmpty(map)) {
            return null;
        }
        AssertUtils.isTrue(map.entrySet().stream().allMatch(o ->
                StringUtils.containsNone(o.getKey(), ';', ':') && StringUtils.containsNone(o.getValue(), ';', ':')
        ), ApiExceptionEnum.PARAM_NOT_VALID, "字段中不能包含 ';', ':' ");
        return StringUtils.join(map.entrySet().stream().map(entry -> entry.getKey() + ":" + entry.getValue()).collect(Collectors.toList()), ";");
    }

    public static List<Long> bytesToLongList(byte[] bytes) {
        if(bytes == null){
            return new ArrayList<Long>();
        }
        int size = bytes != null ? bytes.length : 0;
        if (size == 0 || size % Long.BYTES != 0) {
            return Lists.newArrayList();
        }
        ByteBuffer wrap = ByteBuffer.wrap(bytes);
        List<Long> idList = new ArrayList<>(size / Long.BYTES);
        for (int i = 0; i < size; i += Long.BYTES) {
            idList.add(wrap.getLong(i));
        }
        return idList;
    }

    public static byte[] longListToBytes(List<Long> longList) {
        if (CollectionUtils.isEmpty(longList)) {
            return null;
        }
        ByteBuf byteBuf = Unpooled.buffer(longList.size() * Long.BYTES);
        longList.forEach(byteBuf::writeLong);
        return byteBuf.array();
    }

    public static Set<Long> bytesToLongSet(byte[] bytes) {
        int size = bytes != null ? bytes.length : 0;
        if (size == 0 || size % Long.BYTES != 0) {
            return Sets.newHashSet();
        }
        ByteBuffer wrap = ByteBuffer.wrap(bytes);
        Set<Long> idList = new HashSet<>(size / Long.BYTES);
        for (int i = 0; i < size; i += Long.BYTES) {
            idList.add(wrap.getLong(i));
        }
        return idList;
    }

    public static byte[] longSetToBytes(Set<Long> longSet) {
        if (CollectionUtils.isEmpty(longSet)) {
            return null;
        }
        ByteBuf byteBuf = Unpooled.buffer(longSet.size() * Long.BYTES);
        longSet.forEach(byteBuf::writeLong);
        return byteBuf.array();
    }

    public static List<Float> bytesToFloatList(byte[] bytes) {
        int size = bytes != null ? bytes.length : 0;
        if (size == 0 || size % Float.BYTES != 0) {
            return Lists.newArrayList();
        }
        ByteBuffer wrap = ByteBuffer.wrap(bytes);
        List<Float> idList = new ArrayList<>(size / Float.BYTES);
        for (int i = 0; i < size; i += Float.BYTES) {
            idList.add(wrap.getFloat(i));
        }
        return idList;
    }

    public static byte[] floatListToBytes(List<Float> floatList) {
        if (CollectionUtils.isEmpty(floatList)) {
            return null;
        }
        ByteBuf byteBuf = Unpooled.buffer(floatList.size() * Float.BYTES);
        floatList.forEach(byteBuf::writeFloat);
        return byteBuf.array();
    }

    public static List<Integer> bytesToIntList(byte[] bytes) {
        int size = bytes != null ? bytes.length : 0;
        if (size == 0 || size % Integer.BYTES != 0) {
            return Lists.newArrayList();
        }
        ByteBuffer wrap = ByteBuffer.wrap(bytes);
        List<Integer> idList = new ArrayList<>(size / Integer.BYTES);
        for (int i = 0; i < size; i += Integer.BYTES) {
            idList.add(wrap.getInt(i));
        }
        return idList;
    }

    public static byte[] intListToBytes(List<Integer> intList) {
        if (CollectionUtils.isEmpty(intList)) {
            return null;
        }
        ByteBuf byteBuf = Unpooled.buffer(intList.size() * Integer.BYTES);
        intList.forEach(byteBuf::writeInt);
        return byteBuf.array();
    }

    public static <T> List<T> bytesToObjectList(byte[] problems) {
        //将取出的二进制数据反序列化成序列化的对象，依旧使用对象流处理
        if (problems == null) {
            return new ArrayList<>();
        }
        try (ByteArrayInputStream byteInt = new ByteArrayInputStream(problems);
             ObjectInputStream objInt = new ObjectInputStream(byteInt)) {
            List<T> o = (List<T>) objInt.readObject();
            return o;
        } catch (IOException | ClassNotFoundException e) {
            throw new ApiException(ApiExceptionEnum.PARAM_NOT_VALID, "数据反序列化错误");
        }
    }

    public static <T> byte[] objectListToBytes(List<T> dtoList) {
        try (ByteArrayOutputStream byt = new ByteArrayOutputStream();
             ObjectOutputStream obj = new ObjectOutputStream(byt)) {
            obj.writeObject(dtoList);
            return byt.toByteArray();
        } catch (IOException e) {
            throw new ApiException(ApiExceptionEnum.PARAM_NOT_VALID, "参数序列化错误");
        }
    }
}
